/*
 * 
 * LegendShop 多用户商城系统
 * 
 *  版权所有,并保留所有权利。
 * 
 */
package com.legendshop.permission.controller;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;

import com.legendshop.dao.support.PageSupport;
import com.legendshop.framework.commond.State;
import com.legendshop.framework.commond.StateImpl;
import com.legendshop.framework.compare.DataListComparer;
import com.legendshop.framework.controller.AdminController;
import com.legendshop.framework.controller.BaseController;
import com.legendshop.oa.constants.FunctionEnum;
import com.legendshop.oa.constants.PathResolver;
import com.legendshop.oa.exception.BusinessException;
import com.legendshop.oa.exception.ErrorCodes;
import com.legendshop.oa.model.Function;
import com.legendshop.oa.model.Menu;
import com.legendshop.oa.model.Permission;
import com.legendshop.oa.model.PerssionId;
import com.legendshop.oa.model.Role;
import com.legendshop.oa.model.UserDto;
import com.legendshop.oa.security.UserManager;
import com.legendshop.oa.util.PageSupportHelper;
import com.legendshop.permission.common.PermissionComparator;
import com.legendshop.permission.form.FunctionForm;
import com.legendshop.permission.form.FunctionMenuDto;
import com.legendshop.permission.form.FunctionMenuListDto;
import com.legendshop.permission.page.SecurityBackPage;
import com.legendshop.permission.page.SecurityFowardPage;
import com.legendshop.permission.page.SecurityRedirectPage;
import com.legendshop.permission.page.SecurityTilesPage;
import com.legendshop.permission.service.FunctionService;
import com.legendshop.permission.service.MenuManager;
import com.legendshop.permission.service.MenuService;
import com.legendshop.permission.service.RightDelegate;
import com.legendshop.util.AppUtils;

/**
 * 角色管理器.
 */
@Controller
@RequestMapping("/admin/member/role")
public class RoleAdminController extends BaseController implements AdminController<Role, Long> {
	
	/** The log. */
	private final static Logger log = LoggerFactory.getLogger(RoleAdminController.class);

	/** The basket service. */
	@Autowired(required = false)
	private RightDelegate rightDelegate;
	
	/**
	 * 权限服务
	 */
	@Autowired
	private FunctionService functionService;
	
	@Autowired
	private MenuManager menuManager;
	
	/**
	 * 菜单服务
	 */
	@Autowired
	private MenuService menuService;

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.legendshop.core.base.AdminController#delete(javax.servlet.http.
	 * HttpServletRequest, javax.servlet.http.HttpServletResponse,
	 * java.lang.Object)
	 */

	@RequestMapping(value = "/delete/{id}")
	public String delete(HttpServletRequest request, HttpServletResponse response, @PathVariable Long id) {

		log.info("Struts Action deleteRoleById with id  " + id);
		State state = new StateImpl();

		rightDelegate.deleteRoleById(id, state);

		return PathResolver.getPath(request, response, SecurityRedirectPage.ALL_ROLE);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.legendshop.core.base.AdminController#load(javax.servlet.http.
	 * HttpServletRequest, javax.servlet.http.HttpServletResponse)
	 */

	@RequestMapping("/load")
	public String load(HttpServletRequest request, HttpServletResponse response) {
		return PathResolver.getPath(request, response, SecurityTilesPage.SAVE_ROLE);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.legendshop.core.base.AdminController#query(javax.servlet.http.
	 * HttpServletRequest, javax.servlet.http.HttpServletResponse,
	 * java.lang.String, java.lang.Object)
	 */

	@RequestMapping("/query")
	public String query(HttpServletRequest request, HttpServletResponse response, String curPageNO, Role role) {
		String userName = UserManager.getUserName(request);
		if (userName == null) {
			throw new BusinessException("not login yet", ErrorCodes.BUSINESS_ERROR);
		}
		
		State state = new StateImpl();
		PageSupport<Role> ps = rightDelegate.findAllRolePage(curPageNO,role, state);
		PageSupportHelper.savePage(request, ps);
		request.setAttribute("bean", role);

		return PathResolver.getPath(request, response, SecurityTilesPage.ROLE_LIST);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.legendshop.core.base.AdminController#save(javax.servlet.http.
	 * HttpServletRequest, javax.servlet.http.HttpServletResponse,
	 * java.lang.Object)
	 */

	@RequestMapping(value = "/save")
	public String save(HttpServletRequest request, HttpServletResponse response, Role role) {

		State state = new StateImpl();

		Long id = role.getId();

		if (id == null) {
			id = rightDelegate.saveRole(role, state);
		} else {
			rightDelegate.updateRole(role, state);
		}

		log.info("success saveRole,id = " + id);

		return PathResolver.getPath(request, response, SecurityRedirectPage.ALL_ROLE);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.legendshop.core.base.AdminController#update(javax.servlet.http.
	 * HttpServletRequest, javax.servlet.http.HttpServletResponse,
	 * java.lang.Object)
	 */

	@RequestMapping(value = "/update/{id}")
	public String update(HttpServletRequest request, HttpServletResponse response, @PathVariable Long id) {
		log.info("Action update with id  " + id);
		State state = new StateImpl();
		Role role = rightDelegate.findRoleById(id, state);
		request.setAttribute("bean", role);

		return PathResolver.getPath(request, response, SecurityTilesPage.SAVE_ROLE);
	}

	/**
	 * 查询该角色拥有的用户
	 * userName: 改为昵称 
	 */
	@RequestMapping(value = "/loadUserByRole")
	public String loadUserByRole(HttpServletRequest request, HttpServletResponse response, String curPageNO,String userName,Long roleId){
		if (AppUtils.isBlank(roleId)) {
			return null;
		}

		/////  分页查询 ////////
   		 PageSupport<UserDto> ps = functionService.loadUserByRole(curPageNO,userName,roleId );
   		PageSupportHelper.savePage(request, ps);
   		request.setAttribute("roleId", roleId);
   		request.setAttribute("userName", userName);
		return PathResolver.getPath(request, response, SecurityTilesPage.ROLE_USER_LIST_PAGE);
	}
	
	/**
	 *  
	 *  根据角色分配权限
	 * 
	 * @param request
	 *            the request
	 * @param response
	 *            the response
	 * @param id
	 *            the id
	 * @return the string
	 */
	@RequestMapping(value = "/addFunctions/{roleId}")
	public String addFunctions(HttpServletRequest request, HttpServletResponse response, @PathVariable Long roleId) {
		log.info("addFunctions for roleId  " + roleId);
		List<Function> authorizeFunctions;
		
		State state = new StateImpl();
		Role role = rightDelegate.findRoleById(roleId, state);
		request.setAttribute("bean", role);
		String appNo = role.getAppNo();
		
		//判断是否有VIEW_ALL_DATA权限，如果有，则加载所有的权限
		if(UserManager.hasFunction(request, FunctionEnum.FUNCTION_VIEW_ALL_DATA.value())){
			authorizeFunctions = functionService.getAllFunction(appNo);
		} else {
			authorizeFunctions = functionService.getFunctionByUserId(UserManager.getUserId(request), appNo);
		}

		//组装包装类, 存储同一个菜单Menu_Id下的权限数据, 格式为： 二级menuId: List<Function>
		Map<Menu, List<Function>> menuFunctionList = new HashMap<Menu, List<Function>>();
		
		for (Function function : authorizeFunctions) {
			Long menuId = function.getMenuId();
			Menu top2Menu = menuManager.getParentMenu(menuId); //取第二级菜单
			Menu currentMenu = menuManager.getCurrentMenu(menuId); //取当前及的菜单
			if(top2Menu != null && currentMenu != null && currentMenu.getGrade().equals(3)){//取第三级菜单
				if (menuFunctionList.containsKey(top2Menu)) {
					menuFunctionList.get(top2Menu).add(function);
				} else {
					List<Function> list = new ArrayList<Function>();
					list.add(function);
					menuFunctionList.put(top2Menu, list);
				}
			}

		}
		
		//有相同父节点的权限。  格式： topMenuName: List<FunctionMenuDto>
		Map<Menu, List<FunctionMenuDto>> menuNameFunctionMap = new HashMap<Menu, List<FunctionMenuDto>>();
		List<FunctionMenuDto> resultFuncList = new ArrayList<FunctionMenuDto>();
		List<FunctionMenuListDto> goupList = new ArrayList<FunctionMenuListDto>();
		
		for (Map.Entry<Menu, List<Function>> entry : menuFunctionList.entrySet()) {
			Menu menu = entry.getKey();
			List<Function> funcList = entry.getValue();
			FunctionMenuDto funcWrapper = new FunctionMenuDto();
			funcWrapper.setFuncList(funcList);
			funcWrapper.setMenuName(menu.getName());
			funcWrapper.setMenuId(menu.getMenuId());
			
			resultFuncList.add(funcWrapper);
			
			if(menuNameFunctionMap.containsKey(menu)) {
				menuNameFunctionMap.get(menu).add(funcWrapper);
			} else {
				List<FunctionMenuDto> list = new ArrayList<FunctionMenuDto>();
				list.add(funcWrapper);
				menuNameFunctionMap.put(menu, list);
			}
		}
		
		for (Map.Entry<Menu, List<FunctionMenuDto>> entry : menuNameFunctionMap.entrySet()) {
			Menu menu = entry.getKey();
			List<FunctionMenuDto> funcList = entry.getValue();
			FunctionMenuListDto groupWrapper = new FunctionMenuListDto();
			groupWrapper.setFuncWrapperList(funcList);
			groupWrapper.setMenuName(menu.getName());
			goupList.add(groupWrapper);
		}
		
		//已经有的权限
		List<Function> selectedList = rightDelegate.findFunctionByRoleId(roleId, state);
		
		request.setAttribute("list", selectedList);
		
		//普通权限
		request.setAttribute("resultFuncList", goupList);
		
		//授权的系统权限
		List<Function> authorizeSysFunctions = functionService.getSysFunctionByUserId(UserManager.getUserId(request), appNo);
		
		//判断是否有VIEW_ALL_DATA权限，如果有，则加载所有的权限
		if(UserManager.hasFunction(request, FunctionEnum.FUNCTION_VIEW_ALL_DATA.value())){
			authorizeSysFunctions = functionService.getSysFunctionByAppNo(appNo);
		} else {
			authorizeSysFunctions = functionService.getSysFunctionByUserId(UserManager.getUserId(request), appNo);
		}
		
		request.setAttribute("authorizeSysFunctions", authorizeSysFunctions);


		//根据角色分配权限
		return PathResolver.getPath(request, response, SecurityTilesPage.ROLE_FUNCTION);
	}

	/**
	 * Other functions.
	 * 
	 * @param request
	 *            the request
	 * @param response
	 *            the response
	 * @param curPageNO
	 *            the cur page no
	 * @param id
	 *            the id
	 * @return the string
	 */
	@RequestMapping(value = "/otherFunctions/{id}")
	public String otherFunctions(HttpServletRequest request, HttpServletResponse response, String curPageNO, @PathVariable Long id) {

		State state = new StateImpl();
		Role role = rightDelegate.findRoleById(id, state);
		PageSupport<Function> ps = rightDelegate.findOtherFunctionByHql(curPageNO, id, state);
		PageSupportHelper.savePage(request, ps);

		request.setAttribute("bean", role);

		return PathResolver.getPath(request, response, SecurityBackPage.FIND_OTHER_FUNCTION_LIST);
	}

	/**
	 * 保存权限到角色功能.
	 * 
	 */
	@RequestMapping("/saveFunctionsToRole")
	public String saveFunctionsToRole(HttpServletRequest request, HttpServletResponse response, Long roleId,String funcId) {
		if (AppUtils.isBlank(funcId)) {
			return PathResolver.getPath(request, response, SecurityFowardPage.FIND_FUNCTION_BY_ROLE.getNativeValue() + "/" + roleId,
					SecurityFowardPage.FIND_FUNCTION_BY_ROLE);
		}
		
		State state = new StateImpl();
		DataListComparer<Permission, Permission> comparer = new DataListComparer<Permission, Permission>(new PermissionComparator());
		
		List<Permission> dbList = functionService.getPermissionByRoleId(roleId);
		List<Permission> permDtoList = constructPermission(roleId, funcId);
		Map<Integer, List<Permission>> compareResult = comparer.compare(permDtoList, dbList, null);
		
		//List<Permission> lsUpdateSkuList = compareResult.get(0); //不会有update 列表，直接更新
		List<Permission> delPermList = compareResult.get(-1);
		List<Permission> addPermList = compareResult.get(1);
		
		if (AppUtils.isNotBlank(addPermList)) {
			rightDelegate.saveFunctionsToRole(addPermList, state);
		}
		
		if (AppUtils.isNotBlank(delPermList)) {
			rightDelegate.deleteFunctionsFromRole(delPermList, state);
		}
		
		
		//发布更新菜单指令 TODO
		request.setAttribute("saveStatus", "1");
		
		String path = PathResolver.getPath(request, response, SecurityFowardPage.FIND_FUNCTION_BY_ROLE.getNativeValue() + "/" + roleId,
				SecurityFowardPage.FIND_FUNCTION_BY_ROLE);
		return path;
	}
	
	/**
	 * 组建外部传过来的权限
	 * @param roleId
	 * @param funcIds
	 * @return
	 */
	private List<Permission> constructPermission(Long roleId,String funcIds){
		if(AppUtils.isBlank(funcIds)){
			return null;
		}
		String[] funcList = funcIds.split(",");
		if(AppUtils.isBlank(funcList)){
			return null;
		}
		
		List<Permission> permList =  new ArrayList<Permission>();
		for (String funcId : funcList) {
			Permission p = new Permission(roleId, Long.parseLong(funcId));
			permList.add(p);
		}
		return permList;
	}

	/**
	 * Delete permission by role id.
	 * 
	 * @param request
	 *            the request
	 * @param response
	 *            the response
	 * @param roleId
	 *            the role id
	 * @param functionForm
	 *            the function form
	 * @return the string
	 */
	@RequestMapping("/deletePermissionByRoleId")
	public String deletePermissionByRoleId(HttpServletRequest request, HttpServletResponse response, Long roleId,
			FunctionForm functionForm) {
		log.info("Action deletePermissionByRoleId with roleId {}", roleId);
		List<Permission> permissions = new ArrayList<Permission>();
		String[] strArray = functionForm.getStrArray();
		for (int i = 0; i < strArray.length; i++) {
			Permission permission = new Permission();
			PerssionId perssionId = new PerssionId();
			perssionId.setRoleId(roleId);
			perssionId.setFunctionId(Long.parseLong(strArray[i]));
			permission.setId(perssionId);
			permissions.add(permission);
		}
		State state = new StateImpl();
		rightDelegate.deleteFunctionsFromRole(permissions, state);
		// return
		return PathResolver.getPath(request, response, SecurityRedirectPage.FIND_FUNCTION_BY_ROLE.getNativeValue() + "/" + roleId,
				SecurityRedirectPage.FIND_FUNCTION_BY_ROLE);
	}

}
